package chat_client;

// -----------------------------------------------------------------------------
// Importanweisungen
import for_all.PopUp;
import for_all.Message;
import for_all.Transporter;
import for_all.User;
import for_all.User.LogOutUser;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JViewport;


public class ClientGui extends javax.swing.JFrame {
    
    // Variablendeklarationen
    private Vector<String> userInRoomList;    // Inhalt der JList für User in einem Raum verwalten
    private Vector<String> roomList;          // Inhalt der JList für Räume verwalten
    private Vector<String> userList;          // Liste Aller User verwalten (JList)
    
    private ServerHandler  serverHandler;
    private User           user;
    private PopUp  fail;

    
    // -------------------------------------------------------------------------
    // Konstruktor
    public ClientGui() {
        
        // GUI-Komponenete initialisieren
        initComponents();
        this.textFieldNachrichtVerschicken.setEnabled(false);
        this.buttonNachrichtVerschicken.setEnabled(false);
        this.panelStartPrivateChat.setVisible(false);
        this.textFieldNachrichtVerschicken.setText("Du musst in einen Raum eintreten oder einen Private Chat starten, um Nachrichten verschicken zu können.");
        
        this.userInRoomList = new Vector();
        this.userList       = new Vector();
        this.roomList       = new Vector();
        
    }
    
    
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPopupMenu1 = new javax.swing.JPopupMenu();
        jPopupMenu2 = new javax.swing.JPopupMenu();
        tabbedPaneProtokoll = new javax.swing.JTabbedPane();
        scrollPaneProtokoll = new javax.swing.JScrollPane();
        textAreaProtokoll = new javax.swing.JTextArea();
        panelNachrichtVerschicken = new javax.swing.JPanel();
        buttonNachrichtVerschicken = new javax.swing.JButton();
        textFieldNachrichtVerschicken = new javax.swing.JTextField();
        tabbedPaneUserRooms = new javax.swing.JTabbedPane();
        scrollPaneRäume = new javax.swing.JScrollPane();
        listRäume = new javax.swing.JList();
        scrollPaneBenutzerRaum = new javax.swing.JScrollPane();
        listBenutzerRaum = new javax.swing.JList();
        scrollPaneBenutzerAlle = new javax.swing.JScrollPane();
        listBenutzerAlle = new javax.swing.JList();
        panelStartPrivateChat = new javax.swing.JPanel();
        buttonStartPrivateChat = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Einhornchatsystem");

        tabbedPaneProtokoll.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                tabbedPaneProtokollStateChanged(evt);
            }
        });

        scrollPaneProtokoll.setName(""); // NOI18N

        textAreaProtokoll.setEditable(false);
        textAreaProtokoll.setColumns(20);
        textAreaProtokoll.setRows(5);
        textAreaProtokoll.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        textAreaProtokoll.setName(""); // NOI18N
        scrollPaneProtokoll.setViewportView(textAreaProtokoll);

        tabbedPaneProtokoll.addTab("Server", scrollPaneProtokoll);
        scrollPaneProtokoll.getAccessibleContext().setAccessibleName("");

        panelNachrichtVerschicken.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Nachricht übermitteln", javax.swing.border.TitledBorder.LEFT, javax.swing.border.TitledBorder.TOP));

        buttonNachrichtVerschicken.setText("senden");
        buttonNachrichtVerschicken.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonNachrichtVerschickenActionPerformed(evt);
            }
        });

        textFieldNachrichtVerschicken.setNextFocusableComponent(buttonNachrichtVerschicken);
        textFieldNachrichtVerschicken.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                textFieldNachrichtVerschickenKeyPressed(evt);
            }
        });

        javax.swing.GroupLayout panelNachrichtVerschickenLayout = new javax.swing.GroupLayout(panelNachrichtVerschicken);
        panelNachrichtVerschicken.setLayout(panelNachrichtVerschickenLayout);
        panelNachrichtVerschickenLayout.setHorizontalGroup(
            panelNachrichtVerschickenLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelNachrichtVerschickenLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(textFieldNachrichtVerschicken)
                .addGap(18, 18, 18)
                .addComponent(buttonNachrichtVerschicken)
                .addContainerGap())
        );
        panelNachrichtVerschickenLayout.setVerticalGroup(
            panelNachrichtVerschickenLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(panelNachrichtVerschickenLayout.createSequentialGroup()
                .addGroup(panelNachrichtVerschickenLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(textFieldNachrichtVerschicken, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(buttonNachrichtVerschicken))
                .addContainerGap())
        );

        tabbedPaneUserRooms.setMinimumSize(new java.awt.Dimension(263, 83));
        tabbedPaneUserRooms.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                tabbedPaneUserRoomsStateChanged(evt);
            }
        });

        listRäume.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
            public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
                listRäumeValueChanged(evt);
            }
        });
        scrollPaneRäume.setViewportView(listRäume);

        tabbedPaneUserRooms.addTab("Räume", scrollPaneRäume);

        scrollPaneBenutzerRaum.setViewportView(listBenutzerRaum);

        tabbedPaneUserRooms.addTab("Benutzer (Raum)", scrollPaneBenutzerRaum);

        listBenutzerAlle.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
            public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
                listBenutzerAlleValueChanged(evt);
            }
        });
        scrollPaneBenutzerAlle.setViewportView(listBenutzerAlle);

        tabbedPaneUserRooms.addTab("Benutzer (Alle)", scrollPaneBenutzerAlle);

        buttonStartPrivateChat.setText("Wähle einen private Chat Partner!");
        buttonStartPrivateChat.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonStartPrivateChatActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout panelStartPrivateChatLayout = new javax.swing.GroupLayout(panelStartPrivateChat);
        panelStartPrivateChat.setLayout(panelStartPrivateChatLayout);
        panelStartPrivateChatLayout.setHorizontalGroup(
            panelStartPrivateChatLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(buttonStartPrivateChat, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        panelStartPrivateChatLayout.setVerticalGroup(
            panelStartPrivateChatLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelStartPrivateChatLayout.createSequentialGroup()
                .addGap(11, 11, 11)
                .addComponent(buttonStartPrivateChat, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE))
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(panelNachrichtVerschicken, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(tabbedPaneProtokoll, javax.swing.GroupLayout.DEFAULT_SIZE, 531, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addComponent(tabbedPaneUserRooms, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(panelStartPrivateChat, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(tabbedPaneProtokoll)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(tabbedPaneUserRooms, javax.swing.GroupLayout.DEFAULT_SIZE, 312, Short.MAX_VALUE)
                        .addGap(0, 0, 0)
                        .addComponent(panelStartPrivateChat, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(panelNachrichtVerschicken, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents
    
    
    //<editor-fold defaultstate="collapsed" desc="GUI - Event-Handler">
    
    // -------------------------------------------------------------------------
    // Nachricht durch Button klick abschicken
    private void buttonNachrichtVerschickenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonNachrichtVerschickenActionPerformed
        
        // Prüfen ob eine Nachricht eingegeben wurde
        if (!"".equals(this.textFieldNachrichtVerschicken.getText())) {
            
            // Private Chat oder Raum?
            if (this.tabbedPaneProtokoll.getTitleAt(this.tabbedPaneProtokoll.getSelectedIndex()) == null ? this.user.getRoomName() == null : this.tabbedPaneProtokoll.getTitleAt(this.tabbedPaneProtokoll.getSelectedIndex()).equals(this.user.getRoomName())) {   
                Message nachricht = new Message(this.textFieldNachrichtVerschicken.getText(), this.user.getUserName(), this.tabbedPaneProtokoll.getTitleAt(this.tabbedPaneProtokoll.getSelectedIndex()), false);
                this.serverHandler.sendMessage(nachricht);
                this.setMessage(nachricht);
            } else {
                Message nachricht = new Message(this.textFieldNachrichtVerschicken.getText(), this.user.getUserName(), "private Chat: " + this.tabbedPaneProtokoll.getTitleAt(this.tabbedPaneProtokoll.getSelectedIndex()), true);
                this.serverHandler.sendMessage(nachricht);
                this.setMessage(new Message(this.textFieldNachrichtVerschicken.getText(), this.tabbedPaneProtokoll.getTitleAt(this.tabbedPaneProtokoll.getSelectedIndex()), this.tabbedPaneProtokoll.getTitleAt(this.tabbedPaneProtokoll.getSelectedIndex()), true));
            }
            
            // Nachrichteeingabefeld leeren
            this.textFieldNachrichtVerschicken.setText("");
            
        } else {
            this.fail = new PopUp(this, "Hast du auch Inhalte zu bieten? Dann lasse uns daran teilhaben ;-)", "Leere Nachricht");
        }
        
    }//GEN-LAST:event_buttonNachrichtVerschickenActionPerformed

    
    // -------------------------------------------------------------------------
    // Nachricht durch ENTER abschicken
    private void textFieldNachrichtVerschickenKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_textFieldNachrichtVerschickenKeyPressed
        
        // ENTER-Taste wurde gedrückt
        if(evt.getKeyCode() == java.awt.event.KeyEvent.VK_ENTER) {
            this.buttonNachrichtVerschicken.doClick();
        }
        
    }//GEN-LAST:event_textFieldNachrichtVerschickenKeyPressed
   
    
    // -------------------------------------------------------------------------
    // eine private Unterhaltung initiieren / beenden
    private void buttonStartPrivateChatActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonStartPrivateChatActionPerformed
        
        // starten oder beenden?
        if (this.buttonStartPrivateChat.getText() == null ? "Unterhaltung mit " + this.getUserNameFromListEntry((String)listBenutzerAlle.getSelectedValue()) + " beenden." == null : this.buttonStartPrivateChat.getText().equals("Unterhaltung mit " + getUserNameFromListEntry((String)this.listBenutzerAlle.getSelectedValue()) + " beenden.")) {
            
            // Nachricht an Server
            this.serverHandler.removePrivateChat(getUserNameFromListEntry((String)this.listBenutzerAlle.getSelectedValue()));
        
             // Tab schließen
            this.removePrivateChatTab(getUserNameFromListEntry((String)this.listBenutzerAlle.getSelectedValue()), true);
            
            // Button beschriftung entspr. ändern
            this.buttonStartPrivateChat.setText("Unterhaltung mit " + getUserNameFromListEntry((String)this.listBenutzerAlle.getSelectedValue()) + " starten.");
        } else {
            
            // Nachricht an Server
            this.serverHandler.initiatePrivateChat(getUserNameFromListEntry((String)this.listBenutzerAlle.getSelectedValue()));
        
            // Tab aufmachen
            this.setNewPrivateChat(getUserNameFromListEntry((String)this.listBenutzerAlle.getSelectedValue()));
            
            // Button beschriftung entspr. ändern
            this.buttonStartPrivateChat.setText("Unterhaltung mit " + getUserNameFromListEntry((String)this.listBenutzerAlle.getSelectedValue()) + " beenden.");
        }
    }//GEN-LAST:event_buttonStartPrivateChatActionPerformed

    
    // -------------------------------------------------------------------------
    // Eingabefenster für Nachrichten nicht bei Server-Tab aktiv
    private void tabbedPaneProtokollStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_tabbedPaneProtokollStateChanged
        
        // Wenn ServerTab ausgewählt
        if (this.tabbedPaneProtokoll.getSelectedIndex() == 0) {
            this.textFieldNachrichtVerschicken.setEnabled(false);
            this.textFieldNachrichtVerschicken.setText("Du musst in einen Raum eintreten oder einen Private Chat starten, um Nachrichten verschicken zu können.");
            this.buttonNachrichtVerschicken.setEnabled(false);
        } else {
            this.textFieldNachrichtVerschicken.setEnabled(true);
            this.textFieldNachrichtVerschicken.setText("");
            this.buttonNachrichtVerschicken.setEnabled(true);
        }
    }//GEN-LAST:event_tabbedPaneProtokollStateChanged

    
    // -------------------------------------------------------------------------
    // neuer Raum wurde ausgewählt --> aus alten ausloggen und in neuen gehen
    private void listRäumeValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_listRäumeValueChanged
        if (this.listRäume.getSelectedValue() != null) {
            
            // Variablendeklarationen
            ArrayList<String> liste;
            JScrollPane scrollPane;
            JTextArea   roomTextArea;
            
            try { // Interrupted Exception 
            
                // in Raum einloggen
                String roomName = this.listRäume.getSelectedValue().toString();
            
                // wenn User bereits in diesem Raum, dann abbrechen
                if(user.getRoomName() == null ? roomName == null : user.getRoomName().equals(roomName)) {
                    return;
                }
              
                liste = this.serverHandler.joinRoom(roomName);    
            
                try {   // Tab setzen (wenn schon ein RaumTab offen ist, versuchen diesen zu benutzten)
                    
                    scrollPane   = (JScrollPane)this.tabbedPaneProtokoll.getComponentAt(this.tabbedPaneProtokoll.indexOfTab(user.getRoomName()));
                    roomTextArea = (JTextArea)((JViewport)scrollPane.getComponent(0)).getComponent(0);
                    
                    roomTextArea.setText("");
                    this.tabbedPaneProtokoll.setTitleAt(1, roomName);
                    user.setRoom(roomName);
                
                    
                // wenn noch kein RaumTab da ist einen erstellen
                } catch (IndexOutOfBoundsException | java.lang.ClassCastException ex) {
                 
                    // RaumTab initialisieren
                    scrollPane   = new JScrollPane();
                    roomTextArea = new JTextArea();
                    scrollPane.setBorder(BorderFactory.createEmptyBorder());
                    roomTextArea.setEditable(false);

                   this.tabbedPaneProtokoll.add(scrollPane);
                   this.tabbedPaneProtokoll.setTitleAt(1, roomName);
                   scrollPane.setViewportView(roomTextArea);
                    
                    this.user.setRoom(roomName);
                }
            
                // User des Raums in Userliste setzten
                if (liste != null) {  
                    
                    this.userInRoomList.clear();
                
                    for(String temp : liste) {
                        this.userInRoomList.add(temp);
                    }
                
                    this.listBenutzerRaum.setListData(userInRoomList);
                    this.sortRoomUser();
                    this.listBenutzerRaum.revalidate();
                    
                } else {
                    this.userInRoomList.clear();
                    this.listBenutzerRaum.setListData(userInRoomList);
                    this.sortRoomUser();
                    this.listBenutzerRaum.revalidate();
                }
                
                // Message in Server-Tab schreiben    
                this.setMessage(new Message( "Du hast den Raum " + roomName + " betreten.", "Admin", "Server", false));
                
                // Tabnamen setzen
                this.tabbedPaneProtokoll.setSelectedIndex(this.tabbedPaneProtokoll.indexOfTab(roomName));
                
            } catch (InterruptedException ex) {
                this.fail = new PopUp(this, "InterruptedException: " + ex.getMessage(), "Fehler in listRäumeValueChanged", PopUp.MessageTyp.Error);
            }
        }
    }//GEN-LAST:event_listRäumeValueChanged
  
    
    // -------------------------------------------------------------------------
    // User wurde ausgewählt --> Button zum starten / beenden von private Chat anzeigen
    private void listBenutzerAlleValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_listBenutzerAlleValueChanged
        
        if (this.listBenutzerAlle.getSelectedValue() != null) {
            if (this.tabbedPaneProtokoll.indexOfTab(getUserNameFromListEntry((String)this.listBenutzerAlle.getSelectedValue())) == -1) {
                this.buttonStartPrivateChat.setText("Unterhaltung mit " + getUserNameFromListEntry((String)this.listBenutzerAlle.getSelectedValue()) + " starten.");
            } else {
                this.buttonStartPrivateChat.setText("Unterhaltung mit " + getUserNameFromListEntry((String)this.listBenutzerAlle.getSelectedValue()) + " beenden.");
            }
            this.panelStartPrivateChat.setVisible(true);
            
        } else {
            this.panelStartPrivateChat.setVisible(false);            
        }
    }//GEN-LAST:event_listBenutzerAlleValueChanged

    
    // -------------------------------------------------------------------------
    // Button für Private Chat nur bei Reiter User anzeigen
    private void tabbedPaneUserRoomsStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_tabbedPaneUserRoomsStateChanged
        if (this.tabbedPaneUserRooms.getSelectedIndex() == 0 || this.tabbedPaneUserRooms.getSelectedIndex() == 1) {
            this.panelStartPrivateChat.setVisible(false);
            this.buttonStartPrivateChat.setText("Wähle einen private Chat Partner!");
        } else if (this.tabbedPaneUserRooms.getSelectedIndex() == 2){
            this.panelStartPrivateChat.setVisible(true);
        }
    }//GEN-LAST:event_tabbedPaneUserRoomsStateChanged
    
    // </editor-fold> 
    
    
    //<editor-fold defaultstate="collapsed" desc="GUI - SET/GET/REMOVE-Funktionen">
    
    // -------------------------------------------------------------------------
    // neue Raumliste setzten
    public void setRoomNames(ArrayList<String> liste) {
        
        roomList.clear();
        
        for(String temp: liste) {
            roomList.add(temp);
        }
        
        listRäume.setListData(roomList);
        listRäume.revalidate();
    
    }
    
    
    // -------------------------------------------------------------------------
    // Message fürs Protokoll für bestimmten Raum
    public void setMessage (Message mes) {
       
        if (!mes.getPrivate()) {
   
            JTextArea textArea = this.getTextArea(mes.getRoomName()); 
            
            if (textArea != null) {
            
                // Message hinzufügen
                if ("".equals(textArea.getText())) {
                    textArea.setText(mes.getMessage());
                } else {
                    textArea.append("\n" + mes.getMessage());
                }
                
                // nach unten scrollen
                textArea.setCaretPosition(textArea.getText().length());
                
                if ("Du wurdest verwarnt!".equals(mes.getPureText())) {
                    this.fail = new PopUp(this, "Du bist hiermit offiziell verwarnt!", "Verwarnung", PopUp.MessageTyp.Warning);
                }
                
            }
            
        } else {
            
            JTextArea textArea = this.getTextArea(mes.getSender());
            
            if (textArea != null) {
                
                // Message hinzufügen
                if ("".equals(textArea.getText())) {
                    if (mes.getRoomName() == null ? mes.getSender() == null : mes.getRoomName().equals(mes.getSender())) { // ich habe die nachricht verschickt
                        textArea.setText(new Message(mes.getPureText(), this.user.getUserName(), "blabla", true).getMessage());
                    } else {
                        textArea.setText(mes.getMessage());
                   }
                } else {
                   if (mes.getRoomName() == null ? mes.getSender() == null : mes.getRoomName().equals(mes.getSender())) { // ich habe die nachricht verschickt
                       textArea.setText(new Message(mes.getPureText(), this.user.getUserName(), "blabla", true).getMessage());
                   } else {
                        textArea.append("\n" + mes.getMessage());
                   }
                }
                    
                // nach unten scrollen
                textArea.setCaretPosition(textArea.getText().length()); 
             
            }
        }
    }
    
    
    // -------------------------------------------------------------------------
    // neuer anderer User im Raum
    public void setNewUserInRoom(String userName) {
        
        String temp = null;
        
        if(listBenutzerRaum.getSelectedValue() != null) {
            temp = listBenutzerRaum.getSelectedValue().toString();
        }
        
        userInRoomList.add(userName);
        listBenutzerRaum.setListData(userInRoomList);
        
        if(temp != null) {
            listBenutzerRaum.setSelectedValue(temp, true);
        }
        
        this.sortRoomUser();
        listBenutzerRaum.revalidate();
        
        // Message in Raum-Tab abssetzen
        this.setMessage(new Message( userName + " hat den Raum betreten.", "Admin", this.tabbedPaneProtokoll.getTitleAt(1), false));
    }
    
    
    // -------------------------------------------------------------------------
    // anderer User verlässt den Raum
    public void setUserLeavedRoom(String userName) {
        
        this.userInRoomList.remove(userName);
        this.listBenutzerRaum.setListData(this.userInRoomList);
        this.sortRoomUser();
        this.listBenutzerRaum.revalidate();
        
        // Message in Raum-Tab absetzen
        this.setMessage(new Message( userName + " hat den Raum verlassen.", "Admin", this.tabbedPaneProtokoll.getTitleAt(1), false));
    }
    
    
    // -------------------------------------------------------------------------
    // ein Raumname wurde geändert
    public void setRoomNameChanged(String oldName, String newName) {
        
        String selectedRoom = null;
        
        // Um ihn nach der Aktualisierung wieder zu setzen
        if(this.listRäume.getSelectedValue() != null) {
            selectedRoom = this.listRäume.getSelectedValue().toString();
        }
        
        
        
        // Falls der User im geänderten Raum war
        // --> Änderung an den Nutzer übergeben
        if (this.user.getRoomName() != null && this.user.getRoomName().compareTo(oldName) == 0) {
            this.user.setRoom(newName);
            if (this.tabbedPaneProtokoll.getTitleAt(this.tabbedPaneProtokoll.indexOfTab(oldName)) == null ? oldName == null : this.tabbedPaneProtokoll.getTitleAt(this.tabbedPaneProtokoll.indexOfTab(oldName)).equals(oldName)) {
                this.tabbedPaneProtokoll.setTitleAt(this.tabbedPaneProtokoll.indexOfTab(oldName), newName);
            }
        }
        
        this.roomList.remove(oldName);
        this.roomList.add(newName);
        this.sortRooms();
        this.listRäume.setListData(roomList);
        
        if (selectedRoom != null) {
            if (oldName.compareTo(selectedRoom) == 0) {
                selectedRoom = newName;
            }
            listRäume.setSelectedValue(selectedRoom, true);
        }

        listRäume.revalidate();
        
        raumNamenAendern(oldName, newName); //Änderungen auch in die Liste aller Nutzer eintragen
        
        // Message in Server-Tab absetzen
        this.setMessage(new Message("Der Raum " + oldName + " heißt jetzt " + newName + ".", "Admin", "Server", false));
    }
    
    
    // -------------------------------------------------------------------------
    // ändert alle oldName in der Liste aller Benutzer zu newName
    private void raumNamenAendern(String oldName, String newRoomName) {
        String selected = null;
        if(listBenutzerAlle.getSelectedValue() != null) {
            selected = listBenutzerAlle.getSelectedValue().toString();
        } 
        
        for(int i=0; i < userList.size(); i++) {
            // wenn ein richtiger Eintrag gefunden wurde ersetzen
            if(oldName.compareTo(getRoomNameFromListEntry(this.userList.elementAt(i))) == 0) {
                String newEntry = getUserNameFromListEntry(this.userList.elementAt(i));
                newEntry += " [" + newRoomName + "]";
                if((selected != null) && (selected.compareTo(userList.elementAt(i)) == 0)) {
                    selected = newEntry;
                }
                this.userList.setElementAt(newEntry, i);
            }
        }
        
        this.sortUserList();
        this.listBenutzerAlle.setListData(userList);
        listBenutzerAlle.setSelectedValue(selected, true);
        listBenutzerAlle.revalidate();
    }
    
    
    // -------------------------------------------------------------------------
    // Neuer Raum wurde angelegt
    public void setNewRoomCreated(String roomName) {
        
        String temp = null;
        
        if(listRäume.getSelectedValue() != null) {
            temp = listRäume.getSelectedValue().toString();
        }
        
        roomList.add(roomName);
        listRäume.setListData(roomList);
        
        if(temp != null) {
            listRäume.setSelectedValue(temp, true);
        }
        
        listRäume.revalidate();
        
        // Message in Server-Tab setzen
        this.setMessage(new Message("Der Raum " + roomName + " wurde angelegt.", "Admin", "Server", false));
    }
    
    
    // -------------------------------------------------------------------------
    // Raum wurde gelöscht
    public void setRoomDeleted(String roomName) {
        
        if(user.getRoomName() != null && user.getRoomName().compareTo(roomName) == 0) { //User ist in gelöschtem raum
            this.user.setRoom(null);
            this.fail = new PopUp(this, "Der Raum " + roomName + "wurde entfernt. Bitte wähle doch einen anderen aus.", "Raum entfernt");
            this.tabbedPaneProtokoll.remove(this.tabbedPaneProtokoll.indexOfTab(roomName));
            
            userInRoomList.clear();                       //
            listBenutzerRaum.setListData(userInRoomList); //Liste der Benutzer in diesem (gelöschten) Raum leeren
            listBenutzerRaum.revalidate();                //
        }
        
        String temp = null;
        if(listRäume.getSelectedValue() != null) {
            temp = listRäume.getSelectedValue().toString();
        }
        
        roomList.remove(roomName);
        listRäume.setListData(roomList);
        
        if (temp != null) {   
            if(temp.compareTo(roomName) != 0) {
                listRäume.setSelectedValue(temp, true);
            }
        }
        
        listRäume.revalidate();
        
        // Änderungen auch in die Liste aller Nutzer eintragen
        raumNamenAendern(roomName, "--null--");
        
        // Message in Server-Tab setzen
        this.setMessage(new Message( "Der Raum " + roomName + " wurde entfernt.", "Admin", "Server", false));
    }
    
    
    // -------------------------------------------------------------------------
    // Liefert Username aus Listeneintrag zurück
    private String getUserNameFromListEntry(String listEntry) {
        return listEntry.substring(0, listEntry.lastIndexOf("[")-1);//In der Liste aller Benutzer sind raumname und username durch tab getrennt
    }
    
    
    // -------------------------------------------------------------------------
    // Liefert Raumname aus Listeneintrag zurück
    private String getRoomNameFromListEntry(String listEntry) {
        return listEntry.substring(listEntry.indexOf("[", 0)+1, listEntry.length()-1);
    }
    
    
    // -------------------------------------------------------------------------
    // User kommt / geht
    public void setUser(String usr, String room, boolean setMessage) {
        
        // gehen oder kommen?
        if (!this.userList.contains(usr + " [" + room + "]")) {
            
            this.userList.add(usr + " [" + room + "]");
            
            // Message in Server-Tab setzen
            if (setMessage) {
                this.setMessage(new Message( usr + " ist nun online.", "Admin", "Server", false));
            }
            
        } else {
            
            if (this.tabbedPaneProtokoll.indexOfTab(usr) != -1) {
                this.removePrivateChatTab(usr, false);
            }
        
            this.userList.remove(usr + " [" + room + "]");
            
            // Message in Server-Tab setzen
            this.setMessage(new Message( usr + " ist nun offline.", "Admin", "Server", false));
        }
        
        this.listBenutzerAlle.setListData(this.userList);
        this.sortUserList();
        this.listBenutzerAlle.revalidate();
        
    }
    
    
    // -------------------------------------------------------------------------
    // ändert den Raumnamen von UserName in der Liste aller Benutzer
    public void changeUsersRoom(String userName, String roomName) {
        String selected = null;
        if(listBenutzerAlle.getSelectedValue() != null) {
            selected = listBenutzerAlle.getSelectedValue().toString();
        }
        
        for(int i=0; i<userList.size(); i++) {
            
            // wenn der richtige Eintrag gefunden wurde
            if(userName.compareTo(getUserNameFromListEntry(userList.elementAt(i))) == 0) {
                userList.removeElementAt(i);
                userList.add(userName + " [" + roomName + "]");
                
                if(selected != null && userName.compareTo(getUserNameFromListEntry(selected)) == 0) {
                    selected = userName + " [" + roomName + "]";
                }
                
                listBenutzerAlle.setListData(userList);
                this.sortUserList();
                if(selected != null) {
                    listBenutzerAlle.setSelectedValue(selected, true);
                }
                listBenutzerAlle.revalidate();
                break; //Wurde der richtige Eintrag gefunden, so brauchen die anderen nicht mehr angesehen werden
            }   
        }
    }
    
    
    // -------------------------------------------------------------------------
    // automatisches Ausloggen beim Schließen des Fensters
    public void setLogOutOnClose() {
     
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                serverHandler.getTransporter().sendObject(new LogOutUser(LogOutUser.LogoutReason.ClientClosed));
                serverHandler.stopClient();
         }});
        
    }   // setLogOutOnClose
    
    
    // -------------------------------------------------------------------------
    // einen neuen privaten Chat einrichten
    public void setNewPrivateChat(String name) {
        
            JScrollPane scrollPane;
            JTextArea   textArea;
            
                 
            // Raum initialisieren
            scrollPane = new JScrollPane();
            textArea   = new JTextArea();
            scrollPane.setBorder(BorderFactory.createEmptyBorder());
            textArea.setEditable(false);
                  
            // ins JTabbedPane einfügen
            this.tabbedPaneProtokoll.add(name, scrollPane);
            scrollPane.setViewportView(textArea);
            this.tabbedPaneProtokoll.setSelectedIndex(this.tabbedPaneProtokoll.indexOfTab(name));
  
                
            // Message in Server-Tab schreiben    
            this.setMessage(new Message( "Du hast eine private Unterhaltung mit " + name + " begonnen.", "Admin", "Server", false));
        
            //Falls dieser User ausgewählt wurde, Buttonbeschriftung setzen
            if(listBenutzerAlle.getSelectedValue() != null) {
                String selected = getUserNameFromListEntry(listBenutzerAlle.getSelectedValue().toString());
                if(selected.compareTo(name) == 0) {
                    buttonStartPrivateChat.setText("Unterhaltung mit " + name + " beenden.");
                }
            }
    }
    
    
    // -------------------------------------------------------------------------
    // Tab von privatenChat entfernen
    public void removePrivateChatTab(String title, boolean durchMichBeendet) {
        
        if (this.tabbedPaneProtokoll.indexOfTab(title) != -1) {
        
            this.tabbedPaneProtokoll.remove(this.tabbedPaneProtokoll.indexOfTab(title));
            if (!durchMichBeendet) {    // zusätzlich noch Meldung, wenn nicht durch sich selber beendet
            
                this.fail = new PopUp(this, "Der private Chat mit " + title + " wurde durch " + title + " beendet.", "Privater Chat beendet");
            
                // Button wieder richtig setzen
                if(listBenutzerAlle.getSelectedValue() != null) {
                    String selected = getUserNameFromListEntry(listBenutzerAlle.getSelectedValue().toString());
                    if(title.compareTo(selected) == 0) {
                        this.buttonStartPrivateChat.setText("Unterhaltung mit " + title + " starten.");
                    }
                }
            }
        
            // Message in Server-Tab schreiben    
            this.setMessage(new Message( "Du hast eine private Unterhaltung mit " + title + " beendet.", "Admin", "Server", false));
        }
    }
    
    // </editor-fold>    
    

    //<editor-fold defaultstate="collapsed" desc="Hilfsfunktionen">
    
    // -------------------------------------------------------------------------
    // Sortieren der User Liste nach Raumname
    private void sortUserList() {
        Collections.sort(this.userList, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return ((String)o1.subSequence(o1.lastIndexOf("["), o1.lastIndexOf("]"))).compareTo((String)o2.subSequence(o2.lastIndexOf("["), o2.lastIndexOf("]")));
            }
        });
    }
    
    
    // -------------------------------------------------------------------------
    // Sortieren der User in Raum Liste
    private void sortRoomUser() {
        Collections.sort(this.userInRoomList, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return ((String)o1).compareTo((String)o2);
            }
        });
    }

    
    // -------------------------------------------------------------------------
    // Sortieren der User in Raum Liste
    private void sortRooms() {
        Collections.sort(this.roomList, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return ((String)o1).compareTo((String)o2);
            }
        });
    }
    
    
    // -------------------------------------------------------------------------
    // TextArea für best. Titel bestimmen
    private JTextArea getTextArea(String title) {
        
        // richtigen Tab + Textfeld bestimmen
        JScrollPane correctScrollPane = (JScrollPane) this.tabbedPaneProtokoll.getComponentAt(this.tabbedPaneProtokoll.indexOfTab(title));
            
            if ((JViewport) correctScrollPane.getComponent(0) != null) {
                JViewport viewPort = (JViewport) correctScrollPane.getComponent(0);
                
                if ((JTextArea) viewPort.getView() != null) {
                    JTextArea textArea = (JTextArea) viewPort.getView();
                    return textArea;
                }
            }
        return null;
    }
    
    // </editor-fold>
    
    
    // -------------------------------------------------------------------------
    // Main-Methode
    public static void main(String args[]) {
        
        final ClientGui clientGUI;
        
        
        // ---------------------------------------------------------------------
        // 1. GUI initialisieren, Verbindung zum Server herstellen,
        //    automatischer LogOut beim schließen des Fensters setzen
        clientGUI = new ClientGui();
        clientGUI.serverHandler = new ServerHandler(new Transporter(1234, "localhost", clientGUI), clientGUI);
        
        
        // nur wenn eine Verbindung augebaut werden konnte weitermachen
        if (clientGUI.serverHandler.getTransporter().isConnected()) {
            clientGUI.setLogOutOnClose();
 
        
            // ---------------------------------------------------------------------
            // 2. ServerHandler initialisieren, starten und LogIn-Prozedur ausführen
            clientGUI.serverHandler.start();
        
            try {
                while (!clientGUI.serverHandler.logIn()){}
            } catch (InterruptedException ex) {
                System.err.println("InterruptedException in main: " + ex.getMessage()); //an dieser Stelle kann das Fehlermeldungsfenster noch nicht verwendet werden
            }
            
            clientGUI.user = clientGUI.serverHandler.getUser();
            ArrayList<String> liste = null;
            
            try {
                liste = clientGUI.serverHandler.getRoomNames();
            } catch (InterruptedException ex) {
                System.err.println("InterruptedException in main: " + ex.getMessage()); //an dieser Stelle kann das Fehlermeldungsfenster noch nicht verwendet werden
            }
            
            if (liste!=null) {
                clientGUI.setRoomNames(liste);
            }
            
            
            // ---------------------------------------------------------------------
            // 3. Client GUI anzeigen        
            /* Set the Nimbus look and feel */
            //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(ClientGui.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>
        
            /* Create and display the form */
            java.awt.EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    clientGUI.setVisible(true);
                    clientGUI.setTitle(clientGUI.serverHandler.getUser().getUserName());
                }
            });
            
        } else {
            
            // Wenn keine Verbindung hergestellt werden kann, Fenster schließen
            clientGUI.dispose();
            
        }    
    }   // main
    
    
    //<editor-fold defaultstate="collapsed" desc="Generated Code">
    // -------------------------------------------------------------------------
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton buttonNachrichtVerschicken;
    private javax.swing.JButton buttonStartPrivateChat;
    private javax.swing.JPopupMenu jPopupMenu1;
    private javax.swing.JPopupMenu jPopupMenu2;
    private javax.swing.JList listBenutzerAlle;
    private javax.swing.JList listBenutzerRaum;
    private javax.swing.JList listRäume;
    private javax.swing.JPanel panelNachrichtVerschicken;
    private javax.swing.JPanel panelStartPrivateChat;
    private javax.swing.JScrollPane scrollPaneBenutzerAlle;
    private javax.swing.JScrollPane scrollPaneBenutzerRaum;
    private javax.swing.JScrollPane scrollPaneProtokoll;
    private javax.swing.JScrollPane scrollPaneRäume;
    private javax.swing.JTabbedPane tabbedPaneProtokoll;
    private javax.swing.JTabbedPane tabbedPaneUserRooms;
    private javax.swing.JTextArea textAreaProtokoll;
    private javax.swing.JTextField textFieldNachrichtVerschicken;
    // End of variables declaration//GEN-END:variables
//</editor-fold>
    
}